package com.hifar.test.task.render;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.hifar.abi.utils.minio.MinioUtils;
import com.hifar.base.serialNo.service.IBaseSerialNoService;
import com.hifar.constant.SystemConsts;
import com.hifar.enums.ReportTypeEnum;
import com.hifar.fw.utils.id.IdUtils;
import com.hifar.idm.util.ConvertPdfUtil;
import com.hifar.plugins.TextCheckBoxRenderPolicy;
import com.hifar.plugins.TimeRenderPolicy;
import com.hifar.sys.MinioUtil;
import com.hifar.test.entrust.pojo.HfEnvGkEntrust;
import com.hifar.test.entrust.pojo.HfEnvGkPiece;
import com.hifar.test.entrust.service.IHfEnvGkEntrustService;
import com.hifar.test.entrust.service.IHfEnvGkPieceService;
import com.hifar.test.task.pojo.HfEnvTask;
import com.hifar.test.task.service.IHfEnvTaskService;
import com.hifar.test.template.pojo.HfEnvTemplate;
import com.hifar.test.template.service.IHfEnvTemplateService;
import com.hifar.test.test.pojo.*;
import com.hifar.test.test.render.model.TestCurveDataRenderModel;
import com.hifar.test.test.service.*;
import com.hifar.test.unit.constant.UnitConstant;
import com.hifar.test.unit.pojo.HfPrjUnitBase;
import com.hifar.test.unit.service.IHfPrjUnitBaseService;
import org.apache.commons.io.FileUtils;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author AI Assistant
 * @description 任务原始记录渲染
 * @date 2025-10-16
 */
@Component
public class HfEnvTaskOriginalRecordRender {
    
    @Autowired
    private IHfEnvTaskService taskService;
    
    @Autowired
    private IHfEnvTemplateService envTemplateService;
    
    @Autowired
    private IBaseSerialNoService baseSerialNoService;
    
    @Autowired
    private IHfPrjUnitBaseService unitBaseService;
    
    @Autowired
    private IHfEnvGkEntrustService gkEntrustService;
    
    @Autowired
    private IHfEnvGkPieceService gkPieceService;
    
    @Autowired
    private IHfEnvTestService testService;
    
    @Autowired
    private IHfEnvTaskTestRelationService taskTestRelationService;
    
    @Autowired
    private IHfEnvTestPieceService testPieceService;
    
    @Autowired
    private IHfEnvTestCurveDataService testCurveDataService;
    
    @Autowired
    private IHfEnvTestPersonService testPersonService;

    /**
     * 渲染任务原始记录模板
     *
     * @param taskId 任务id
     */
    public void renderReport(String taskId) {
        HfEnvTask hfEnvTask = taskService.getById(taskId);
        Assert.notNull(hfEnvTask, "任务数据不存在!");
        
        String unitId = hfEnvTask.getUnitId();
        HfPrjUnitBase prjUnitBase = unitBaseService.getById(unitId);
        Assert.notNull(prjUnitBase, "试验项目数据不存在!");
        
        String unitType = prjUnitBase.getUnitType();
        HfEnvTemplate reportTemplate = null;
        
        // 根据项目类型选择模板
        if (Objects.equals(UnitConstant.TYPE_DYNAMICS, unitType)) {
            reportTemplate = envTemplateService.getTemplateByType(ReportTypeEnum.DYNAMICS_ORIGINAL_RECORDS);
            Assert.notNull(reportTemplate, "力学原始记录模板不存在!");
        } else {
            reportTemplate = envTemplateService.getTemplateByType(ReportTypeEnum.CLIMATE_ORIGINAL_RECORDS);
            Assert.notNull(reportTemplate, "气候原始记录模板不存在!");
        }
        
        String templatePath = reportTemplate.getTemplatePath();
        String originalCode = baseSerialNoService.getMouthSerialNo(taskId + "TaskOriginal"
                , "yyyyMMdd", "RW-", "", 2);
        
        File tempDirectory = FileUtils.getTempDirectory();
        String templateLocalPath = tempDirectory + File.separator + IdUtils.uuid32() + ".docx";
        String tempPdfPath = null;
        File tempWordFile = null;
        
        try {
            String wordObjectName = "hifar/idm/task/" + originalCode + ".docx";
            String pdfObjectName = "hifar/idm/task/" + originalCode + ".pdf";
            
            // 下载模板到本地
            MinioUtil.downloadFile(MinioUtil.PRE_DEFAULT, templatePath, templateLocalPath);
            
            // 封装数据
            Map<String, Object> pageData = this.packageData(taskId);
            
            // 渲染模板
            tempWordFile = this.render(new File(templateLocalPath), pageData);
            
            // Word 转 PDF
            tempPdfPath = ConvertPdfUtil.wordToPdf(tempWordFile.getAbsolutePath());
            
            // 上传到 MinIO
            MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, wordObjectName, tempWordFile.getAbsolutePath());
            MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, pdfObjectName, tempPdfPath, "application/pdf");

            // 更新任务表
            UpdateWrapper<HfEnvTask> taskUpdateWrapper = new UpdateWrapper<>();
            taskUpdateWrapper.lambda()
                    .set(HfEnvTask::getPdfPathXh, pdfObjectName)
                    .set(HfEnvTask::getDocxPathXh, wordObjectName)
                    .eq(HfEnvTask::getId, taskId);
            taskService.update(taskUpdateWrapper);
            
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("生成任务原始记录失败!");
        } finally {
            // 清理临时文件
            if (new File(templateLocalPath).exists()) {
                new File(templateLocalPath).delete();
            }
            if (Objects.nonNull(tempWordFile)) {
                tempWordFile.delete();
            }
            if (Objects.nonNull(tempPdfPath)) {
                new File(tempPdfPath).delete();
            }
        }
    }

    /**
     * 渲染模板
     */
    private File render(File templateFile, Map<String, Object> data) throws Exception {
        ConfigureBuilder builder = Configure.builder();
        Configure configure = builder.build();
        File tempDirectory = FileUtils.getTempDirectory();

        String tempWordPath = tempDirectory + File.separator + IdUtils.uuid32() + ".docx";
        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
        
        // 注册为表格渲染
        LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
        TimeRenderPolicy timeRenderPolicy2 = new TimeRenderPolicy("yyyy-MM-dd-");
        TimeRenderPolicy timeRenderPolicy3 = new TimeRenderPolicy("yyyy-MM-dd HH:mm");
        TextCheckBoxRenderPolicy textCheckBoxRenderPolicy = new TextCheckBoxRenderPolicy();
        TextCheckBoxRenderPolicy yesTextCheckBoxRenderPolicy2 = new TextCheckBoxRenderPolicy(SystemConsts.YES);
        TextCheckBoxRenderPolicy noTextCheckBoxRenderPolicy = new TextCheckBoxRenderPolicy(SystemConsts.NO);

        builder.addPlugin('<', loopRowTableRenderPolicy);
        builder.addPlugin(':', timeRenderPolicy2);
        builder.addPlugin('$', timeRenderPolicy3);
        builder.addPlugin('-', textCheckBoxRenderPolicy);
        builder.addPlugin('=', yesTextCheckBoxRenderPolicy2);
        builder.addPlugin('!', noTextCheckBoxRenderPolicy);
        builder.bind("testCondition", htmlRenderPolicy);
        
        Configure.ClearHandler clearHandler = new Configure.ClearHandler();
        builder.useSpringEL(false);
        builder.setValidErrorHandler(clearHandler);
        
        XWPFTemplate
                .compile(templateFile.getPath(), configure)
                .render(data)
                .writeAndClose(new FileOutputStream(tempWordPath));
        return new File(tempWordPath);
    }

    /**
     * 封装任务数据（汇总任务下所有试验的数据）
     */
    private Map<String, Object> packageData(String taskId) {
        Map<String, Object> dataMap = new HashMap<>();
        
        HfEnvTask hfEnvTask = taskService.getById(taskId);
        Assert.notNull(hfEnvTask, "任务数据不存在!");
        
        // 任务基本信息
        dataMap.put("unitName", hfEnvTask.getUnitName());
        dataMap.put("standardNames", hfEnvTask.getStandardName());
        dataMap.put("standardCodes", hfEnvTask.getStandardCode());
        dataMap.put("testConditions", hfEnvTask.getTestCondition());
        
        // 查询任务下的所有试验
        List<HfEnvTaskTestRelation> taskTestRelationList = taskTestRelationService.lambdaQuery()
                .eq(HfEnvTaskTestRelation::getTaskId, taskId)
                .list();
        
        if (taskTestRelationList.isEmpty()) {
            return dataMap;
        }
        
        List<String> testIdList = taskTestRelationList.stream()
                .map(HfEnvTaskTestRelation::getTestId)
                .collect(Collectors.toList());
        
        List<HfEnvTest> testList = testService.listByIds(testIdList);
        
        // 汇总所有试验的数据
        if (!testList.isEmpty()) {
            // 取第一个试验的基本信息（设备信息等）
            HfEnvTest firstTest = testList.get(0);
            dataMap.put("equipCode", firstTest.getEquipCode());
            dataMap.put("equipModel", firstTest.getEquipModel());
            dataMap.put("equipName", firstTest.getEquipName());
            dataMap.put("checkValid", firstTest.getCheckValid());
            
            // 汇总所有试验编号
            String testCodes = testList.stream()
                    .map(HfEnvTest::getTestCode)
                    .collect(Collectors.joining(","));
            dataMap.put("testCode", testCodes);
            
            // 取最早的开始时间和最晚的结束时间
            Date minStartTime = testList.stream()
                    .map(HfEnvTest::getRealStartTime)
                    .filter(Objects::nonNull)
                    .min(Date::compareTo)
                    .orElse(null);
            Date maxEndTime = testList.stream()
                    .map(HfEnvTest::getRealEndTime)
                    .filter(Objects::nonNull)
                    .max(Date::compareTo)
                    .orElse(null);
            dataMap.put("realStartTime", minStartTime);
            dataMap.put("realEndTime", maxEndTime);
            
            // 汇总备注
            String remarks = testList.stream()
                    .map(HfEnvTest::getRemarks)
                    .filter(Objects::nonNull)
                    .collect(Collectors.joining(";"));
            dataMap.put("remarks", remarks);
            
            // 汇总试验结果
            String testResults = testList.stream()
                    .map(HfEnvTest::getTestResult)
                    .filter(Objects::nonNull)
                    .collect(Collectors.joining(";"));
            dataMap.put("testResult", testResults);
            
            // 汇总过程描述
            String processDescs = testList.stream()
                    .map(HfEnvTest::getProcessDesc)
                    .filter(Objects::nonNull)
                    .collect(Collectors.joining(";"));
            dataMap.put("processDesc", processDescs);
        }
        
        // 统计所有试验的温度范围（最小~最大）
        List<BigDecimal> temperatureList = testList.stream()
                .map(HfEnvTest::getTemperature)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        String temperatureRange = calculateRangeFromBigDecimal(temperatureList);
        dataMap.put("temperature", temperatureRange);
        
        // 统计所有试验的湿度范围（最小~最大）
        List<BigDecimal> humidityList = testList.stream()
                .map(HfEnvTest::getHumidity)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        String humidityRange = calculateRangeFromBigDecimal(humidityList);
        dataMap.put("humidity", humidityRange);
        
        // 汇总所有试验的样品数据
        List<HfEnvTestPiece> allTestPieceList = new ArrayList<>();
        for (String testId : testIdList) {
            List<HfEnvTestPiece> testPieceList = testPieceService.listPieceByTestId(testId);
            allTestPieceList.addAll(testPieceList);
        }
        
        Set<String> productNameSet = new HashSet<>();
        Set<String> productCodeSet = new HashSet<>();
        Set<String> productNoSet = new HashSet<>();
        
        for (HfEnvTestPiece hfEnvTestPiece : allTestPieceList) {
            if (Objects.nonNull(hfEnvTestPiece.getProductName())) {
                productNameSet.add(hfEnvTestPiece.getProductName());
            }
            if (Objects.nonNull(hfEnvTestPiece.getProductCode())) {
                productCodeSet.add(hfEnvTestPiece.getProductCode());
            }
            if (Objects.nonNull(hfEnvTestPiece.getPieceNo())) {
                productNoSet.add(hfEnvTestPiece.getPieceNo());
            }
        }
        
        dataMap.put("productName", String.join(",", productNameSet));
        dataMap.put("productCode", String.join(",", productCodeSet));
        dataMap.put("pieceNo", String.join(",", productNoSet));
        dataMap.put("pieceNum", allTestPieceList.size());
        
        // 汇总所有试验的曲线数据
        List<HfEnvTestCurveData> allTestCurveDataList = new ArrayList<>();
        for (String testId : testIdList) {
            List<HfEnvTestCurveData> testCurveDataList = testCurveDataService.listByTestId(testId);
            allTestCurveDataList.addAll(testCurveDataList);
        }
        
        // 曲线数据按时间排序
        allTestCurveDataList.sort(Comparator.comparing(HfEnvTestCurveData::getRecordTime, 
                Comparator.nullsLast(Comparator.naturalOrder())));
        
        Iterator<HfEnvTestCurveData> testCurveDataIterator = allTestCurveDataList.iterator();
        int testCurveNum = (allTestCurveDataList.size() / 2) + (allTestCurveDataList.size() % 2);
        List<TestCurveDataRenderModel> testCurveDataRenderModelList = new ArrayList<>(testCurveNum);
        
        for (int i = 0; i < testCurveNum; i++) {
            TestCurveDataRenderModel testCurveDataRenderModel = new TestCurveDataRenderModel();
            if (testCurveDataIterator.hasNext()) {
                HfEnvTestCurveData testCurveData = testCurveDataIterator.next();
                testCurveDataRenderModel.setSettingValue1(testCurveData.getTemperature());
                testCurveDataRenderModel.setDisplayValue1(testCurveData.getHumidity());
                testCurveDataRenderModel.setOptUserId1(testCurveData.getOptUserId());
                testCurveDataRenderModel.setOptUserName1(testCurveData.getOptUserName());
                testCurveDataRenderModel.setRecordTime1(testCurveData.getRecordTime());
            }
            if (testCurveDataIterator.hasNext()) {
                HfEnvTestCurveData testCurveData = testCurveDataIterator.next();
                testCurveDataRenderModel.setSettingValue2(testCurveData.getTemperature());
                testCurveDataRenderModel.setDisplayValue2(testCurveData.getHumidity());
                testCurveDataRenderModel.setOptUserId2(testCurveData.getOptUserId());
                testCurveDataRenderModel.setOptUserName2(testCurveData.getOptUserName());
                testCurveDataRenderModel.setRecordTime2(testCurveData.getRecordTime());
            }
            testCurveDataRenderModelList.add(testCurveDataRenderModel);
        }
        
        dataMap.put("curveList", testCurveDataRenderModelList);
        
        // 汇总所有试验的试验人员
        Set<String> testUserNameSet = new HashSet<>();
        for (String testId : testIdList) {
            List<HfEnvTestPerson> testPersonList = testPersonService.listTestTestUser(testId);
            testUserNameSet.addAll(testPersonList.stream()
                    .map(HfEnvTestPerson::getUserName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList()));
        }
        dataMap.put("testUserName", String.join(",", testUserNameSet));
        
        // 委托单信息（从任务关联）
        String gkEntrustId = hfEnvTask.getGkEntrustId();
        if (Objects.nonNull(gkEntrustId)) {
            HfEnvGkEntrust gkEntrust = gkEntrustService.getById(gkEntrustId);
            if (Objects.nonNull(gkEntrust)) {
                dataMap.put("entrustCode", gkEntrust.getEntrustCode());
                dataMap.put("entrustCust", gkEntrust.getEntrustCust());
                dataMap.put("entrustUserName", gkEntrust.getEntrustUserName());
                dataMap.put("subjectName", gkEntrust.getSubjectName());
                dataMap.put("subjectNo", gkEntrust.getSubjectNo());
            }
        }
        
        return dataMap;
    }
    
    /**
     * 计算数值范围（最小~最大）- BigDecimal版本
     * @param valueList BigDecimal数值列表
     * @return 最小~最大的范围字符串
     */
    private String calculateRangeFromBigDecimal(List<BigDecimal> valueList) {
        if (valueList == null || valueList.isEmpty()) {
            return null;
        }
        
        // 计算最小值和最大值
        BigDecimal min = valueList.stream()
                .min(BigDecimal::compareTo)
                .orElse(null);
        BigDecimal max = valueList.stream()
                .max(BigDecimal::compareTo)
                .orElse(null);
        
        if (min == null || max == null) {
            return null;
        }
        
        // 如果最小值等于最大值，只返回一个值
        if (min.compareTo(max) == 0) {
            return min.stripTrailingZeros().toPlainString();
        }
        
        // 返回范围
        String minStr = min.stripTrailingZeros().toPlainString();
        String maxStr = max.stripTrailingZeros().toPlainString();
        return minStr + "~" + maxStr;
    }
    
    /**
     * 计算数值范围（最小~最大）- String版本（保留用于其他场景）
     * @param valueList 数值列表（可能包含范围字符串）
     * @return 最小~最大的范围字符串
     */
    private String calculateRange(List<String> valueList) {
        if (valueList == null || valueList.isEmpty()) {
            return null;
        }
        
        // 提取所有数值
        List<Double> allValues = new ArrayList<>();
        for (String value : valueList) {
            if (value == null || value.trim().isEmpty()) {
                continue;
            }
            // 处理可能已经是范围的情况（如 "20~30"）
            if (value.contains("~")) {
                String[] parts = value.split("~");
                for (String part : parts) {
                    try {
                        allValues.add(Double.parseDouble(part.trim()));
                    } catch (NumberFormatException e) {
                        // 忽略无法解析的部分
                    }
                }
            } else {
                // 处理单个数值
                try {
                    allValues.add(Double.parseDouble(value.trim()));
                } catch (NumberFormatException e) {
                    // 忽略无法解析的值
                }
            }
        }
        
        if (allValues.isEmpty()) {
            return valueList.get(0); // 返回原始值
        }
        
        // 计算最小值和最大值
        double min = allValues.stream().min(Double::compareTo).orElse(0.0);
        double max = allValues.stream().max(Double::compareTo).orElse(0.0);
        
        // 如果最小值等于最大值，只返回一个值
        if (min == max) {
            // 判断是否为整数
            if (min == Math.floor(min)) {
                return String.valueOf((int) min);
            } else {
                return String.valueOf(min);
            }
        }
        
        // 返回范围
        String minStr = (min == Math.floor(min)) ? String.valueOf((int) min) : String.valueOf(min);
        String maxStr = (max == Math.floor(max)) ? String.valueOf((int) max) : String.valueOf(max);
        return minStr + "~" + maxStr;
    }
}

